package parts.spring;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import parts.mass.Mass;
import applet.Simulation;
import applet.forces.Force;


/**
 * Spring holds the information for a spring
 * in the simulation. Each spring has two masses
 * (one on each end). It also tells the simulation
 * how to update each spring on the screen according
 * to the forces applied on it by each mass on its ends.
 *
 * @author Robert C. Duvall
 * edited by Jesse Starr and Guy Tracy
 */
public class Spring {
    private Mass myStart;
    private Mass myEnd;
    private double myLength;
    private double myK;

    /**
     * Creates a spring.
     *
     * @param start first mass it is connected to
     * @param end second mass it is connected to
     * @param length of the spring
     * @param kVal of the spring
     */
    public Spring (Mass start, Mass end, double length, double kVal) {
        myStart = start;
        myEnd = end;
        myLength = length;
        myK = kVal;
    }

    /**
     * Paints the spring on the canvas.
     * @param pen used to paint
     */
    public void paint (Graphics2D pen) {
        int xStart = (int) myStart.getCenter().getX();
        int yStart = (int) myStart.getCenter().getY();
        int xEnd = (int) myEnd.getCenter().getX();
        int yEnd = (int) myEnd.getCenter().getY();
        double dx = xStart - xEnd;
        double dy = yStart - yEnd;
        double len = Math.sqrt(dx * dx + dy * dy) - myLength;

        if (Math.abs(len) < 0.001) {
            pen.setColor(Color.WHITE);
        }
        else if (len < 0.0) {
            pen.setColor(Color.BLUE);
        }
        else {
            pen.setColor(Color.RED);
        }
        pen.drawLine(xStart, yStart, xEnd, yEnd);
    }

    /**
     * Updates the movement of the spring.
     * @param canvas where the spring is painted
     * @param dt time interval passed
     */
    public void update (Simulation canvas, double dt) {
        Point2D start = myStart.getCenter();
        Point2D end = myEnd.getCenter();
        double dx = start.getX() - end.getX();
        double dy = start.getY() - end.getY();

        // apply hooke's law to each attached mass
        Force f = new Force(Force.angleBetween(dx, dy), myK
                * (myLength - Force.distanceBetween(dx, dy)));
        myStart.applyForce(f);
        f.negate();
        myEnd.applyForce(f);
    }

    /**
     * Sets the first mass it is connected to.
     * @param start a mass
     */
    public void setMyStart (Mass start) {
        this.myStart = start;
    }

    /**
     * Gets the first mass it is connected to.
     */
    public Mass getMyStart () {
        return myStart;
    }

    /**
     * Sets the second mass it is connected to.
     * @param end a mass
     */
    public void setMyEnd (Mass end) {
        this.myEnd = end;
    }

    /**
     * Gets the second mass it is connected to.
     */
    public Mass getMyEnd () {
        return myEnd;
    }

    /**
     * Sets the rest length of the spring.
     * @param length is the rest length
     */
    public void setMyLength (double length) {
        this.myLength = length;
    }

    /**
     * Gets the rest length of the spring.
     */
    public double getMyLength () {
        return myLength;
    }

    /**
     * Sets the k value of the spring.
     * @param k is the k value
     */
    public void setMyK (double k) {
        this.myK = k;
    }

    /**
     * Gets the k value of the spring.
     */
    public double getMyK () {
        return myK;
    }
}
